Skip to content

Adds Call Traces — per-turn STT/LLM/TTS latency for voice agent calls. - #123

Open
MSami625 wants to merge 66 commits into
mainfrom
otel-traces
Open

Adds Call Traces — per-turn STT/LLM/TTS latency for voice agent calls.#123
MSami625 wants to merge 66 commits into
mainfrom
otel-traces

Conversation

@MSami625

@MSami625 MSami625 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

What Changed?

Adds Call Traces — per-turn STT/LLM/TTS latency for voice agent calls.

  • New /api/v1/observability/traces API (session create, OTLP ingest, list/detail, close)
  • DB tables for trace storage (078_synthetic_call_traces)
  • Pipecat integration SDK (efficientai.integrations.efficientai_traces) for external bots
  • In-process OTLP export for playground voice agents
  • Call Traces UI with waterfall, charts, and turn breakdown
  • Trace panels on evaluator results, playground calls, and observability views
  • Pipecat example bots + local test scripts

Why?

Reviewers need per-turn latency (STT / LLM / TTS) during playground runs, phone evals, and external Pipecat agents. This adds OTLP-based trace ingest correlated by call_short_id, so latency is visible in one place in the UI.

How to Test?

  1. Run eai start-all and confirm migration 078 applied.
  2. API smoke test:
    export EFFICIENTAI_API_KEY="..." EFFICIENTAI_WORKSPACE_ID="..."
    uv run python scripts/test_local_pipecat_trace.py
  3. Pipecat WebRTC: follow docs/synthetic-call-traces-pipecat.md → talk 2–3 turns → check Call Traces UI.
  4. Playground: run a voice agent call → confirm trace panel on call detail.
  5. Evaluator: run a trace-enabled eval → confirm trace on result detail.
  6. Run tests:
    uv run pytest tests/test_synthetic_trace_*.py tests/test_efficientai_traces_correlation.py tests/test_services/test_playground_tracing.py -q

Release Label

Select one semantic version bump intent for this PR:

  • major - breaking change, next release bumps major version
  • minor - backward-compatible feature, next release bumps minor version
  • fix - backward-compatible bug fix, next release bumps patch version
  • No label (defaults to patch release)

Intended release label: minor

Checklist

  • [x ] I have read the CONTRIBUTING.md guide.
  • [x ] My code follows the project's style guidelines.
  • [x ] I have added tests that prove my fix is effective or my feature works.
  • [x ] I have updated documentation where needed.

MSami625 and others added 30 commits August 7, 2026 19:02
…n events and audio billing; enhance CSP policy for frame sources
…g evaluator result creation and usage tracking;
…oducing patching for blob storage and integrating new storage stubs
…processing; improve error handling during database commits
…call usage tracking; update test to reflect new behavior
… tests; update configuration and service logic to prevent external API calls
… conversation tracking in test agents and voice agents
…and update configuration for Flexprice setup
…icense features to canonical meters with dry-run option
…ribe functionality and updating configuration options
…pt partial AI assistance, enhancing tracking for generated prompts and scenarios
…information and updating event handling for playground calls and fix sarvam ai flooding logs
@MSami625

MSami625 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile-apps

@greptile-apps

greptile-apps Bot commented Sep 3, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds end-to-end call tracing for voice sessions, including OTLP ingestion, durable trace storage, SDK and playground instrumentation, and trace visualizations.

  • Adds workspace-scoped trace session, ingest, list, detail, correlation, and close APIs.
  • Adds synthetic trace models, migration, span mapping, latency aggregation, and call/evaluator linkage.
  • Adds Pipecat tracing helpers and in-process playground exporting.
  • Adds frontend waterfall, chart, turn-detail, and call-detail integrations.

Confidence Score: 3/5

The PR is not safe to merge until provider webhook updates are constrained to the resolved workspace to prevent cross-workspace call mutation and disclosure.

Provider identifiers supplied by a webhook are used in an organization-only call-record lookup; a collision selects a sibling-workspace record, overwrites its persisted call data and lifecycle state, and returns that data to the caller.

Files Needing Attention: app/api/v1/routes/observability.py

Security Review

The provider webhook upsert can overwrite and disclose a sibling workspace's call record when caller-supplied provider identifiers collide, because its existing-record lookup omits the resolved workspace.

How this was verified: The webhook-supplied identifiers flow into an organization-only lookup whose matched record is mutated and serialized with call data.

Important Files Changed

Filename Overview
app/api/v1/routes/observability.py Adds call-detail and provider-ingestion behavior, but the provider webhook upsert can mutate and return a sibling-workspace record because its lookup omits workspace scope.
app/api/v1/routes/synthetic_traces.py Adds authenticated, workspace-scoped trace session, ingest, listing, correlation, and detail endpoints; the previously reported backfill route now supplies the active workspace.
app/services/synthetic_traces/trace_service.py Implements trace creation, correlation, backfill, span ingestion, turn derivation, and finalization, with the normal backfill selection now scoped by organization and workspace.
app/services/voice_agent/playground_tracing.py Initializes one in-process exporter and stamps each playground call's organization, workspace, and call identifiers into its spans, resolving the prior mutable-exporter correlation issue.
app/services/synthetic_traces/internal_otlp_exporter.py Groups exported spans by their own organization, workspace, and call attributes rather than mutable per-call exporter state.
app/migrations/078_synthetic_call_traces.py Adds persistence structures for trace headers, turn payloads, and OTLP payloads.
frontend/src/components/call-recordings/SyntheticCallTracePanel.tsx Adds the primary call-trace presentation panel integrating latency summaries and detailed trace views.

Reviews (3): Last reviewed commit: "chore: remove Confluence scratch files a..." | Re-trigger Greptile

Comment thread app/services/voice_agent/playground_tracing.py Outdated
Comment thread app/api/v1/routes/synthetic_traces.py
…ll recording source and audio streaming capabilities
…nd routes enhancing performance and maintainability
@MSami625

MSami625 commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile-apps

MSami625 and others added 5 commits September 5, 2026 16:48
…in span correlation and improve span grouping logic
Integrate simulation upgrades, evaluator results dashboard, persona ambient
noise, and test-agent playground UX with synthetic call traces, OTLP
ingestion, and unified call recording panels. Preserves per-span tenant
isolation for in-process playground telemetry export.

Co-authored-by: Cursor <cursoragent@cursor.com>
Restores ListIntegrationVoiceAgentsResponse and IntegrationVoiceAgentListItem
dropped during main merge so the API server can start.

Co-authored-by: Cursor <cursoragent@cursor.com>
…-events

Repair post-merge regressions: unified /calls routes, evaluator transcript resolution,
trace lookup by call_short_id, live telephony SSE, playground re-evaluate, and full
test-agent result details.

Co-authored-by: Cursor <cursoragent@cursor.com>
…guard

Delete tracked .tmp-* Confluence/MCP artifacts, gitignore future scratch files,
restore skipped_playground webhook protection, and align observability list test
with unified /calls hub behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
@MSami625

MSami625 commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile-apps

Comment on lines +197 to +205
call_recording = (
db.query(CallRecording)
.filter(
CallRecording.organization_id == organization_id,
CallRecording.provider_call_id == provider_call_id,
CallRecording.provider_platform == provider_platform,
)
.first()
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Webhook crosses workspace boundary

When a webhook submits a provider platform and call ID matching a non-playground recording in another workspace of the same organization, this lookup selects that recording, overwrites its call data and lifecycle fields, and returns its call data to the webhook caller. Constrain the existing-record lookup to the workspace already resolved for this ingestion.

How this was verified: The webhook-supplied identifiers flow into an organization-only lookup whose matched record is mutated and serialized with include_data=True.

Suggested change
call_recording = (
db.query(CallRecording)
.filter(
CallRecording.organization_id == organization_id,
CallRecording.provider_call_id == provider_call_id,
CallRecording.provider_platform == provider_platform,
)
.first()
)
call_recording = (
db.query(CallRecording)
.filter(
CallRecording.organization_id == organization_id,
CallRecording.workspace_id == workspace_id,
CallRecording.provider_call_id == provider_call_id,
CallRecording.provider_platform == provider_platform,
)
.first()
)

Knowledge Base Used:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant